# coding: utf-8
from typing import Union

from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QColor
from PySide6.QtWidgets import QWidget, QVBoxLayout, QButtonGroup
from qfluentwidgets import SingleDirectionScrollArea, PushButton, FluentIconBase, \
    HorizontalSeparator, Theme, isDarkTheme
from qfluentwidgets.components.navigation.navigation_panel import NavigationItemPosition

from common import StyleSheet


class CustomNavigationButton(PushButton):
    def _postInit(self):
        self.setCheckable(True)
        self.setFixedSize(200, 40)
        StyleSheet.NavigationBar.apply(self)

    def _drawIcon(self, icon, painter, rect, state: QIcon.State = QIcon.State.Off):
        if isinstance(icon, FluentIconBase):
            if not isDarkTheme():
                if self.isChecked():
                    icon = icon.icon(color=QColor(255, 255, 255))
                else:
                    icon = icon.icon(color=QColor('#8B96D9'))
            else:
                if self.isChecked():
                    icon = icon.icon(color=QColor(0, 0, 0))
                else:
                    icon = icon.icon(color=QColor(255, 255, 255))
        elif not self.isEnabled():
            painter.setOpacity(0.786 if isDarkTheme() else 0.9)
            if isinstance(icon, FluentIconBase):
                icon = icon.icon(Theme.DARK)

        PushButton._drawIcon(self, icon, painter, rect, state)


class CustomNavigationBar(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self.scrollArea = SingleDirectionScrollArea(self)
        self.scrollWidget = QWidget()
        self.buttonGroup = QButtonGroup(self)

        self.vBoxLayout = QVBoxLayout(self)
        self.topLayout = QVBoxLayout()
        self.bottomLayout = QVBoxLayout()
        self.scrollLayout = QVBoxLayout(self.scrollWidget)

        self.__initWidget()

    def __initWidget(self):
        self.resize(48, self.height())
        self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground)
        self.window().installEventFilter(self)

        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.scrollArea.setWidget(self.scrollWidget)
        self.scrollArea.setWidgetResizable(True)

        self.scrollWidget.setObjectName('scrollWidget')
        StyleSheet.NavigationBar.apply(self)
        StyleSheet.NavigationBar.apply(self.scrollWidget)
        self.__initLayout()

    def __initLayout(self):
        self.vBoxLayout.setContentsMargins(5, 5, 5, 5)
        self.topLayout.setContentsMargins(4, 0, 4, 0)
        self.bottomLayout.setContentsMargins(4, 0, 4, 0)
        self.scrollLayout.setContentsMargins(4, 0, 4, 0)
        self.vBoxLayout.setSpacing(4)
        self.topLayout.setSpacing(4)
        self.bottomLayout.setSpacing(4)
        self.scrollLayout.setSpacing(4)

        self.vBoxLayout.addLayout(self.topLayout, 0)
        self.vBoxLayout.addWidget(self.scrollArea)
        self.vBoxLayout.addLayout(self.bottomLayout, 0)

        self.vBoxLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.topLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.scrollLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.bottomLayout.setAlignment(Qt.AlignmentFlag.AlignBottom)

    def button(self):
        return self.buttonGroup.buttons()

    def addSeparator(self, position=NavigationItemPosition.TOP):
        self.insertSeparator(-1, position)

    def insertSeparator(self, index: int, position=NavigationItemPosition.TOP):
        separator = HorizontalSeparator(self)
        self.addWidget(index, separator, position)

    def _insertWidgetToLayout(self, index: int, widget: QWidget, position: NavigationItemPosition):
        """ insert widget to layout """
        if position == NavigationItemPosition.TOP:
            widget.setParent(self)
            self.topLayout.insertWidget(index, widget, 0, Qt.AlignmentFlag.AlignTop)
        elif position == NavigationItemPosition.SCROLL:
            widget.setParent(self.scrollWidget)
            self.scrollLayout.insertWidget(index, widget, 0, Qt.AlignmentFlag.AlignTop)
        else:
            widget.setParent(self)
            self.bottomLayout.insertWidget(index, widget, 0, Qt.AlignmentFlag.AlignBottom)

        widget.show()

    def addWidget(self, index: int, widget: QWidget, position=NavigationItemPosition.TOP):
        self._insertWidgetToLayout(index, widget, position)

    def insertItem(self, index: int, icon: Union[str, QIcon, FluentIconBase], text: str,
                   position=NavigationItemPosition.TOP):
        """ insert navigation tree item

        Parameters
        ----------
        index: int
            the insert position of parent widget

        icon: str | QIcon | FluentIconBase
            the icon of navigation item

        text: str
            the text of navigation item
       """
        w = CustomNavigationButton(icon, text, self)
        self.addWidget(index, w, position)
        self.buttonGroup.addButton(w)
        return w

    def addItem(self, icon: Union[str, QIcon, FluentIconBase], text: str, position=NavigationItemPosition.TOP):
        return self.insertItem(-1, icon, text, position=position)
